package com.gitee.limaozhi.nio.example02;

import com.gitee.limaozhi.util.Utils;
import org.apache.commons.lang.RandomStringUtils;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

/**
 * @author hzlimaozhi
 * @date 2019/12/20 11:17
 */
public class Client {

    private static void client() throws IOException {
        // 1. 创建socket
        SocketChannel socketChannel = SocketChannel.open();
        // 2. 设置为非阻塞
        socketChannel.configureBlocking(false);

        // 3. 发起连接
        boolean success = socketChannel.connect(new InetSocketAddress(8000));
        if (success) {
            System.out.println("建立连接");
        } else {
            // 4. 完成连接
            // 没有异步回调，只能同步
            // 无法检查状态，只能重试
            for (int i = 1; i < Integer.MAX_VALUE; i++) {
                if (socketChannel.finishConnect()) {
                    System.out.println("建立连接");
                    break;
                } else {
                    System.out.println("connect等待：" + i);
                    Utils.sleepSeconds(1);
                }
            }
        }

        // 足够大（简化问题）的缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024 * 50);

        // 请求
        List<byte[]> requests = new ArrayList<>();
        // 1K
        requests.add(RandomStringUtils.randomAlphanumeric(1024).getBytes());
        // 1M
        requests.add(RandomStringUtils.randomAlphanumeric(1024 * 1024).getBytes());
        // 10M
        requests.add(RandomStringUtils.randomAlphanumeric(1024 * 1024 * 10).getBytes());

        for (int i = 1; i <= requests.size(); i++) {
            System.out.println("第" + i + "次请求：");
            byte[] request = requests.get(i-1);

            // 缓冲区切换写模式
            buffer.clear();
            // 写入缓冲区
//            buffer.put(("第" + i + "次请求：\n").getBytes("UTF-8"));
            buffer.put(request);

            // 切换读模式
            buffer.flip();

            // 4. 发送数据
            for (int j = 1; ; j++) {
                int count = socketChannel.write(buffer);
                System.out.println("第" + j + "次写入：" + count);
                if (buffer.remaining() == 0) {
                    break;
                } else {
                    Utils.sleepSeconds(1);
                }
            }
        }

        // 关闭写通道 => 通知服务端停止读取
        socketChannel.shutdownOutput();

        // 5. 接收数据
        for (int j = 1; ; j++) {
            buffer.clear();

            int count = socketChannel.read(buffer);
            System.out.println("第" + j + "次读取：" + count);
            if (count < 0) {
                break;
            } else if (count == 0) {
                Utils.sleepSeconds(1);
            } else {
                // 切换读模式
                buffer.flip();
                byte[] bytes = new byte[buffer.remaining()];
                buffer.get(bytes);
                System.out.println(new String(bytes));
            }
        }

        socketChannel.close();
    }

    public static void main(String[] args) throws IOException {
        client();
    }

}
